package cn.schoolwow.quickdao.module.database.ddl.action.flow.table;

import cn.schoolwow.quickdao.annotation.IdStrategy;
import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.database.ddl.IndexField;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickdao.module.database.ddl.action.flow.table.common.BuildForeignKeyFlow;
import cn.schoolwow.quickdao.module.database.ddl.common.flow.GetAutoIncrementStatementCommonFlow;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;

import java.util.ArrayList;
import java.util.List;

public class MysqlCreateTableFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        buildColumn(flowContext);
        buildIndex(flowContext);
        flowContext.executeFlowList(new BuildForeignKeyFlow());
        buildTableComment(flowContext);
    }

    @Override
    public String name() {
        return "mysql数据库创建表";
    }

    private void buildColumn(FlowContext flowContext) throws Exception {
        Entity entity = flowContext.checkData("entity", Entity.class);
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);

        StringBuilder sqlBuilder = new StringBuilder();
        flowContext.putTemporaryData("sqlBuilder", sqlBuilder);

        sqlBuilder.append("create table " + quickDAOConfig.databaseContext.databaseProvider.escape(entity.tableName));
        if (!entity.properties.isEmpty()) {
            sqlBuilder.append("(");
        }
        for (Property property : entity.properties) {
            if (property.id && property.strategy == IdStrategy.AutoIncrement) {
                flowContext.startFlow(new GetAutoIncrementStatementCommonFlow())
                        .putTemporaryData("propertyOption", property)
                        .execute();
            } else {
                sqlBuilder.append(quickDAOConfig.databaseContext.databaseProvider.escape(property.column) + " " + property.columnType + (null == property.range ? "" : "(" + property.range + ")"));
                if (null!=property.notNull&&property.notNull) {
                    sqlBuilder.append(" not null");
                }
                if (null != property.defaultValue && !property.defaultValue.isEmpty()) {
                    sqlBuilder.append(" default '" + property.defaultValue+"'");
                }
                if (null != property.comment) {
                    sqlBuilder.append(" " + quickDAOConfig.databaseContext.databaseProvider.comment(property.comment));
                }
                if (null != property.escapeCheck && !property.escapeCheck.isEmpty()) {
                    sqlBuilder.append(" check " + property.escapeCheck);
                }
            }
            sqlBuilder.append(",");
        }
    }

    private void buildIndex(FlowContext flowContext){
        StringBuilder sqlBuilder = flowContext.checkData("sqlBuilder", StringBuilder.class);
        Entity entity = flowContext.checkData("entity", Entity.class);
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);

        List<String> ignoreIndexNameList = new ArrayList<>();
        for (IndexField indexField : entity.indexFieldList) {
            if (null == indexField.columns || indexField.columns.isEmpty()) {
                //忽略该索引
                ignoreIndexNameList.add(indexField.indexName);
                continue;
            }
            switch (indexField.indexType) {
                case UNIQUE: {
                    sqlBuilder.append("unique");
                }
                case NORMAL: {
                    sqlBuilder.append(" index " + quickDAOConfig.databaseContext.databaseProvider.escape(indexField.indexName) + " (");
                    for (String column : indexField.columns) {
                        sqlBuilder.append(quickDAOConfig.databaseContext.databaseProvider.escape(column) + ",");
                    }
                    sqlBuilder.deleteCharAt(sqlBuilder.length() - 1);
                    sqlBuilder.append(")");
                    if (null != indexField.using && !indexField.using.isEmpty()) {
                        sqlBuilder.append(" using " + indexField.using);
                    }
                    if (null != indexField.comment && !indexField.comment.isEmpty()) {
                        sqlBuilder.append(" " + quickDAOConfig.databaseContext.databaseProvider.comment(indexField.comment));
                    }
                    sqlBuilder.append(",");
                }
                break;
                case FULLTEXT: {
                    sqlBuilder.append("fulltext(" + indexField.columns.get(0) + "),");
                }
                break;
            }
        }
        flowContext.putTemporaryData("ignoreIndexNameList", ignoreIndexNameList);
    }

    private void buildTableComment(FlowContext flowContext){
        StringBuilder sqlBuilder = flowContext.checkData("sqlBuilder", StringBuilder.class);
        Entity entity = flowContext.checkData("entity", Entity.class);
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);

        if (!entity.properties.isEmpty()) {
            sqlBuilder.append(")");
        }
        if (null != entity.comment) {
            sqlBuilder.append(" " + quickDAOConfig.databaseContext.databaseProvider.comment(entity.comment));
        }
        sqlBuilder.append(" character set utf8mb4 collate utf8mb4_unicode_ci;");
    }
}
